using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using System.IO;            //Path 
using System.Reflection;    //Assembly 
using System.Xml;

namespace Cards
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        #region Variables
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        //Font to be used to debugging out txt
        SpriteFont font;

        //an underlay to place beneath text to test invisability
        Texture2D blackBox;

        //Deck that gets dealt out to players
        public static Deck playDeck = new Deck(104);

        //Deck of cards in order for the board
        public static Deck boardDeck = new Deck(104);

        //Creates the player input
        Input playerInput;

        //An array of indexes that indicate which card out of the deck a player owns
        public static int[] player1Hand = new int[7];

        //An array of indexes that indicate which card out of the deck a player owns
        public static int[] player2Hand = new int[7];

        //indicates whether or not it is player one or player two's turn
        public static bool isPlayer1Turn;

        public static KeyboardState keyboardState;

        Board gameBoard;

        const int screenWidth = 1067;
        const int screenHeight = 600;

        SoundEffect shuffle;

        Spider aiSpider;

        //load the xml into an XmlDocument 
        XmlDocument doc = new XmlDocument();


          //get all "CARD" nodes  
          XmlNodeList cardNodes;
          //create an array with sufficient space 
          public static int[] board;

          Random random;


          Texture2D winBanner;
          Texture2D loseBanner;



        #endregion

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {

            random = new Random();
        
            //get the executing assembly's folderpath 
            //NOTICE - this is the subfolder "bin/DEBUG" or "bin/RELEASE", NOT the folder with the Program.cs! :) 
            string programFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            //and the path to the html document that displays the generated images 
            string xmlPath = Path.Combine(programFolder, "board.xml");

            cardNodes = doc.SelectNodes("/BOARD_ORIENTATION_1/CARD");
            doc.Load(xmlPath);
            board = new int[cardNodes.Count];
            


            // TODO: Add your initialization logic here
            graphics.PreferredBackBufferWidth = screenWidth;
            graphics.PreferredBackBufferHeight = screenHeight;

            //Create the community deck for the players
            //playDeck.Initialize();
            if (playDeck.Shuffle(3000))
                playDeck.DealHand(playDeck, player1Hand, player2Hand, 6);
            else
            {
                for (int i = 1; i <= 6; i++)
                {
                    player1Hand[i] = 0;
                    player2Hand[i] = 0;
                }
            }

            isPlayer1Turn = true;

            playerInput = new Input(Content);
                                   
            gameBoard = new Board();



            winBanner = Content.Load<Texture2D>
            ("RedWinBanner");
            loseBanner = Content.Load<Texture2D>
                ("BlueWinBanner");



            //int [] cardValues = GetCards(xmlPath); 





          //iterate through the XmlNodes and parse their string values to int 
          for (int cardIndex = 0; cardIndex < cardNodes.Count; cardIndex++)
          {
              board[cardIndex] = int.Parse(cardNodes[cardIndex].InnerText);
          }

          for (int i = 0; i <= 100; i++)
          {
              boardDeck.deck[i] = board[i];
          }

            player2Hand[3] = 33;

            shuffle = Content.Load<SoundEffect>
                ("CardShuffle");

            aiSpider = new Spider();

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            font = Content.Load<SpriteFont>("SpriteFont1");
            blackBox = Content.Load<Texture2D>("BlackBox3");
            gameBoard.LoadContent(Content);

            shuffle.Play();
            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {

            keyboardState = Keyboard.GetState();

            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
                this.Exit();

            // Allows the game to exit
            if (keyboardState.IsKeyDown(Keys.Escape))
                this.Exit();

            // TODO: Add your update logic here
            //playerInput.Update(spriteBatch);

            //Gets the input from the player
            if (playerInput.inHand)//if its time for someone to choose a card from their hand
            {
                if (isPlayer1Turn)//if its the player's turn
                    playerInput.GetHandInput(player1Hand);
                else//if it's the computer's turn
                {

                       // if (aiSpider.ckUp(player2Hand[i], 2) >= 2)
                       // {
                       //     playerInput.cardAndSpotSelection[0] = playerInput.cardAndSpotSelection[1] = player2Hand[i];
                       //     if ((Board.chips[boardDeck.deck[player2Hand[i]]] == Board.chipState.empty && !(playerInput.cardAndSpotSelection[0] == 24 || playerInput.cardAndSpotSelection[0] == 37) || //if empty and not wild
                       //((playerInput.cardAndSpotSelection[0] == 24 || playerInput.cardAndSpotSelection[0] == 37) && (Board.chips[player2Hand[i]] != Board.chipState.empty)) || //or wild and not empty
                       // playerInput.cardAndSpotSelection[1] == 53)) //or free
                       //     {
                       //         playerInput.inHand = true;
                       //         playerInput.keyPress = false;

                       //         Game1.playDeck.DealHand(Game1.playDeck, Game1.player2Hand, playerInput.card);
                       //         Board.chips[boardDeck.deck[player2Hand[i]]] = Board.chipState.p2;
                       //         playerInput.piecePlace2.Play();
                       //         playerInput.endChecker.endCheck(Game1.isPlayer1Turn);
                       //         Game1.isPlayer1Turn = !Game1.isPlayer1Turn;

                       //         playerInput.card = 1;
                       //         break;
                       //     }
                       //     else
                       //     {
                       //         playerInput.wrongMove.Play();
                       //         playerInput.inHand = true;
                       //         playerInput.keyPress = false;
                       //         playerInput.card = 1;
                       //     }
                       // }
                       // else
                        //{

                    QuickAI();
                      // }
                    }

                    //and not the below statement
                    //playerInput.GetHandInput(player2Hand);
                }
            

            if (!playerInput.inHand)//if its a player's turn and time to choose a board piece
            {
                //if its computer's turn, put A.I. stuff here
                playerInput.GetBoardInput(boardDeck);
            }

            //if (endChecker.endCheck(!isPlayer1Turn)) //send the previous player turn to check if they won
            //{
            //    //display win screen
            //}

            //CHEATSORZ!!!!!!!!!!!!!!!!!!!!!
            //boardDeck.deck[100] = 12;
            player1Hand[1] = 11;//add anywhere
            player1Hand[2] = 11;//add anywhere
            player1Hand[3] = 11;
            player1Hand[4] = 11;
            player1Hand[5] = 24;
            player1Hand[6] = 24;

            //player2Hand[1] = 32;
            //player2Hand[2] = 11;
            //player2Hand[3] = 11;
            //player2Hand[4] = 20;
            //player2Hand[5] = 24;
            //player2Hand[6] = 24;

            base.Update(gameTime);
        }

        private void QuickAI()
        {
            int i = random.Next(1, 6);
            int pos = 0;
            playerInput.cardAndSpotSelection[0] = playerInput.cardAndSpotSelection[1] = player2Hand[1];
            for (int x = 0; x < 100; x++)
            {
                if (board[x] == (int)player2Hand[i])
                {
                    pos = x;
                    break;
                }
            }


            if ((Board.chips[pos] == Board.chipState.empty && !(playerInput.cardAndSpotSelection[0] == 24 || playerInput.cardAndSpotSelection[0] == 37) || //if empty and not wild
       ((playerInput.cardAndSpotSelection[0] == 24 || playerInput.cardAndSpotSelection[0] == 37) && (Board.chips[pos] != Board.chipState.empty)) || //or wild and not empty
        playerInput.cardAndSpotSelection[1] == 53)) //or free
            {
                playerInput.inHand = true;
                playerInput.keyPress = false;

                Game1.playDeck.DealHand(Game1.playDeck, Game1.player2Hand, i);
                Board.chips[pos] = Board.chipState.p2;
                playerInput.piecePlace2.Play();
                playerInput.endChecker.endCheck(Game1.isPlayer1Turn);
                Game1.isPlayer1Turn = !Game1.isPlayer1Turn;
                playerInput.card = 1;
                //break;

            }
            else
            {
                QuickAI();

                //playerInput.wrongMove.Play();
                //playerInput.inHand = true;
                //playerInput.keyPress = false;
                //playerInput.card = 1;
            }
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {



            GraphicsDevice.Clear(Color.Black);//new Color(173,216,230,255)

            // TODO: Add your drawing code here
            spriteBatch.Begin();



            //spriteBatch.Draw(blackBox, new Vector2(0, 475), Color.White);

            int loc = 1;

            //hold K to show the playHand during gamePlay
            if (keyboardState.IsKeyDown(Keys.K))
            {
                //draws the board
                loc = 1;
                for (int y = 1; y <= 10; y++)
                {
                    for (int x = 1; x <= 10; x++)
                    {
                        //spriteBatch.DrawString(font, Convert.ToString(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Azure);
                        spriteBatch.DrawString(font, playDeck.TranslateCardToText(playDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Thistle);//new Color(43, 255, 135, 100)
                        loc++;
                    }
                }
            }
            else
            {//hold shift K to display the numbers of playHand
                if (keyboardState.IsKeyDown(Keys.RightShift))
                {
                    //draws the board
                    loc = 1;
                    for (int y = 1; y <= 10; y++)
                    {
                        for (int x = 1; x <= 10; x++)
                        {
                            //spriteBatch.DrawString(font, Convert.ToString(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Azure);
                            spriteBatch.DrawString(font, playDeck.deck[loc].ToString(), new Vector2((x * 65), y * 40), Color.Thistle);//new Color(43, 255, 135, 100)
                            loc++;
                        }
                    }
                }

                else
                {
                    //ptherwise draw the normal board
                    loc = 1;
                    for (int y = 1; y <= 10; y++)
                    {
                        for (int x = 1; x <= 10; x++)
                        {
                            //spriteBatch.DrawString(font, Convert.ToString(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Azure);
                            spriteBatch.DrawString(font, boardDeck.TranslateCardToText(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.DarkRed);//new Color(43, 255, 135, 100)
                            loc++;
                        }
                    }
                }
            }

            ////and draw the top of board in another
            //loc = 1;
            //for (int y = 1; y <= 5; y++)
            //{
            //    for (int x = 1; x <= 10; x++)
            //    {
            //        //spriteBatch.DrawString(font, Convert.ToString(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Azure);
            //        spriteBatch.DrawString(font, boardDeck.TranslateCardToText(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Blue);
            //        loc++;
            //    }
            //}

            //new Color(58,255,131,255)

            //draws player one hand
            for (int i = 1; i <= 6; i++)
            {
                spriteBatch.DrawString(font, boardDeck.TranslateCardToText(player1Hand[i]), new Vector2((i * 65), 480), Color.Blue);//new Color(0,50,25,255)
                //spriteBatch.DrawString(font, Convert.ToString(playDeck.deck[i]), new Vector2((i * 65), 510), Color.Azure);
            }

            //draws player two hand
            for (int i = 1; i <= 6; i++)
            {
                spriteBatch.DrawString(font, boardDeck.TranslateCardToText(player2Hand[i]), new Vector2((i * 65), 520), new Color(43, 255, 135, 100));//Color.Blue
                //spriteBatch.DrawString(font, Convert.ToString(playDeck.deck[i]), new Vector2((i * 65), 510), Color.Azure); new Color(58, 255, 131, 255) new Color(45, 255, 150, 150)//best 
            }
            //spriteBatch.DrawString(font, Convert.ToString(19%11), new Vector2(500, 520), new Color(43, 255, 135, 100));//Color.Blue
            

            ////and draw the top of board in another
            //loc = 1;
            //for (int y = 1; y <= 5; y++)
            //{
            //    for (int x = 1; x <= 10; x++)
            //    {
            //        //spriteBatch.DrawString(font, Convert.ToString(boardDeck.deck[loc]), new Vector2((x * 65), y * 40), Color.Azure);
            //        spriteBatch.DrawString(font, boardDeck.TranslateCardToText(boardDeck.deck[loc+25]), new Vector2((x * 65) + 4, y * 40), new Color(255, 0, 150, 255));
            //        loc++;
            //    }
            //}
        
        
    
        //chips[1] = chipState.p1;
        //chips[2] = chipState.p2;
           


            //spriteBatch.Draw(p1Chip, new Vector2(3*65 + 15, 1 * 40 + 5), new Rectangle(0,0, p1Chip.Width, p1Chip.Height), Color.White, 0, new Vector2(0,0), .5f, 0, 0);

            spriteBatch.End();
            playerInput.Draw(spriteBatch);

            gameBoard.Draw(spriteBatch, playerInput);

            spriteBatch.Begin();

            if (EndGame.drawWin)
            {
                spriteBatch.Draw(winBanner, new Rectangle(-150, 250, winBanner.Width, winBanner.Height),new Rectangle(0,0,winBanner.Width,winBanner.Height), Color.White);
            }
            if (EndGame.drawLose)
            {
                spriteBatch.Draw(loseBanner, new Rectangle(-150, 250, loseBanner.Width, loseBanner.Height), new Rectangle(0, 0, loseBanner.Width, loseBanner.Height), Color.White);
            }

            spriteBatch.End();



            base.Draw(gameTime);
        }
    }
}